import { IPageResponse } from "@/common/CommonType";
import { ValidationError } from "@/utils/errors";
import SysRoleEntity from "./Entity";
import appDataSource from "@/db";
import SysMenuEntity from "../menu/Entity";
import { In } from "typeorm";

export class SysRoleService {
  /**
   * 添加数据
   */
  public static async add(data: SysRoleEntity): Promise<true> {
    // 1. 转换类型
    data = SysRoleEntity.transform(data);
    // 2. 数据验证
    const errors = await data.validateThis();
    if (errors.length > 0) {
      throw new ValidationError(errors[0]);
    }
    const role = appDataSource.getRepository(SysRoleEntity);
    const menu = appDataSource.getRepository(SysMenuEntity);

    // 关联所有菜单
    const relationMenus = await menu.find({
      where: {
        id: In(data.menus as number[]),
      },
    });
    data.menus = relationMenus;

    await role.save(data);
    return true;
  }

  /**
   * 分页获取数据
   */
  public static async findByPage(current: number, size: number, where?: any): Promise<IPageResponse> {
    const rep = appDataSource.getRepository(SysRoleEntity);
    const [list, total] = await rep.findAndCount({
      skip: size * (current - 1),
      take: size,
      where,
      relations: { menus: true },
    });

    list.forEach((item) => {
      item.menus = item.menus.map((menu) => menu.id);
    });

    return {
      total,
      list,
    };
  }

  /**
   * 无分页
   */
  public static async findByList(where?: any) {
    const rep = appDataSource.getRepository(SysRoleEntity);
    return rep.find({
      where,
    });
  }

  /**
   * 通过id获取数据
   */
  public static async findById(id: string) {
    const rep = appDataSource.getRepository(SysRoleEntity);

    const data = await rep.findOne({
      where: { id: +id },
      relations: { menus: true },
    });
    if (data) {
      data.menus = data.menus.map((menu) => menu.id);
    }
    return data;
  }

  /**
   * 修改数据
   */
  public static async update(data: SysRoleEntity) {
    const rep = appDataSource.getRepository(SysRoleEntity);

    const role = await rep.findOne({
      where: {
        id: +data.id,
      },
      relations: {
        menus: true,
      },
    });
    if (!role) {
      throw new Error("角色不存在");
    }

    // 修改数据
    Object.keys(data).forEach((key) => {
      role[key] = data[key];
    });

    // 处理菜单
    if (data.menus) {
      // 删除多余menu
      const alreadyMenu: number[] = [];
      role.menus = (role.menus as SysMenuEntity[]).filter((item) => {
        alreadyMenu.push(item.id);
        return (data.menus as number[]).includes(item.id);
      });

      const sysMenuRep = appDataSource.getRepository(SysMenuEntity);
      for (let i = 0; i < data.menus.length; i++) {
        const id = data.menus[i] as number;

        // 如果这个菜单已经保存在user当中，不需要再添加
        if (alreadyMenu.includes(id)) {
          continue;
        }

        const menus = await sysMenuRep.findOneBy({ id: id });
        menus && role.menus.push(menus);
      }
    }

    await rep.save(role);
    return null;
  }

  /**
   * 删除数据
   */
  public static async delete(id: string) {
    const rep = appDataSource.getRepository(SysRoleEntity);
    const result = await rep.softDelete({ id: +id });
    return result.raw;
  }
}
